select()
, poll()
, এবং epoll()
হলো তিনটি গুরুত্বপূর্ণ সিস্টেম কল, যা নেটওয়ার্ক প্রোগ্রামিংয়ে I/O Multiplexing অর্জনের জন্য ব্যবহৃত হয়। এগুলোর মাধ্যমে একাধিক Socket বা File Descriptor-কে একসাথে পর্যবেক্ষণ করা যায় এবং এক বা একাধিক File Descriptor থেকে ইনপুট পাওয়া গেলে তা প্রক্রিয়া করা যায়। এগুলো বিশেষত নেটওয়ার্ক সার্ভার এবং উচ্চ-পারফরম্যান্স অ্যাপ্লিকেশন ডিজাইন করতে ব্যবহৃত হয়। নিচে প্রতিটি ফাংশনের ব্যবহার, প্রয়োজনীয়তা, এবং উদাহরণ দেওয়া হলো:
select()
select()
একটি পুরনো এবং সাধারণ সিস্টেম কল, যা File Descriptor সেটগুলোকে (Sockets, Files, Pipes ইত্যাদি) পর্যবেক্ষণ করে। এটি নির্দিষ্ট File Descriptor-এ I/O অপারেশন করার জন্য প্রস্তুত কিনা তা চেক করে।
select()
ফাংশনের সিগনেচার (C ভাষায়)int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
nfds
: সর্বোচ্চ File Descriptor এর মান + 1।readfds
: File Descriptor সেট যা Read অপারেশনের জন্য পর্যবেক্ষণ করা হবে।writefds
: File Descriptor সেট যা Write অপারেশনের জন্য পর্যবেক্ষণ করা হবে।exceptfds
: File Descriptor সেট যা Exceptional Condition এর জন্য পর্যবেক্ষণ করা হবে।timeout
: কত সময় অপেক্ষা করবে (একটি টাইমআউট ভ্যালু)।select()
এর উদাহরণ#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <arpa/inet.h>
#define PORT 8080
int main() {
int server_fd, client_fd, max_fd, activity;
struct sockaddr_in server_addr;
fd_set read_fds;
char buffer[1024];
// Server socket তৈরি করা
server_fd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
listen(server_fd, 3);
while (1) {
FD_ZERO(&read_fds);
FD_SET(server_fd, &read_fds);
max_fd = server_fd;
// select() কল করা
activity = select(max_fd + 1, &read_fds, NULL, NULL, NULL);
if (activity > 0 && FD_ISSET(server_fd, &read_fds)) {
client_fd = accept(server_fd, NULL, NULL);
printf("New connection accepted\n");
read(client_fd, buffer, sizeof(buffer));
printf("Received: %s\n", buffer);
close(client_fd);
}
}
close(server_fd);
return 0;
}
poll()
poll()
হলো select()
-এর একটি উন্নত সংস্করণ, যা একাধিক File Descriptor-কে পর্যবেক্ষণ করে এবং I/O অপারেশন করার জন্য প্রস্তুত কিনা তা জানায়। এটি select()
-এর মতো কাজ করে, তবে এটি একটি Array ব্যবহার করে, যা select()
-এর Fixed-Size Set-এর চেয়ে বেশি নমনীয়।
poll()
ফাংশনের সিগনেচার (C ভাষায়)int poll(struct pollfd *fds, nfds_t nfds, int timeout);
fds
: struct pollfd
এর একটি Array যা File Descriptor এবং তাদের Event টাইপ ধারণ করে।nfds
: Array-তে থাকা File Descriptor এর সংখ্যা।timeout
: কতক্ষণ অপেক্ষা করবে (মিলিসেকেন্ডে)।poll()
এর উদাহরণ#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <arpa/inet.h>
#define PORT 8080
int main() {
int server_fd, client_fd;
struct sockaddr_in server_addr;
struct pollfd fds[10];
int nfds = 1;
char buffer[1024];
// Server socket তৈরি করা
server_fd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
listen(server_fd, 3);
fds[0].fd = server_fd;
fds[0].events = POLLIN;
while (1) {
int activity = poll(fds, nfds, -1);
if (activity > 0 && (fds[0].revents & POLLIN)) {
client_fd = accept(server_fd, NULL, NULL);
printf("New connection accepted\n");
read(client_fd, buffer, sizeof(buffer));
printf("Received: %s\n", buffer);
close(client_fd);
}
}
close(server_fd);
return 0;
}
epoll()
epoll()
হলো Linux-এ select()
এবং poll()
এর আরও উন্নত সংস্করণ, যা উচ্চ-পারফরম্যান্স অ্যাপ্লিকেশন এবং সার্ভারের জন্য উপযুক্ত। এটি স্কেলেবিলিটির জন্য ডিজাইন করা হয়েছে এবং অনেক বেশি File Descriptor পরিচালনা করতে সক্ষম। epoll()
ব্যবহারের মাধ্যমে বেশিরভাগ ইভেন্ট-ড্রিভেন সার্ভার এবং অ্যাপ্লিকেশন তৈরি করা হয়।
epoll()
ফাংশনের তিনটি প্রধান অংশepoll_create()
:
epoll
instance তৈরি করে।int epoll_create(int size);
epoll_ctl()
:
epoll
instance-এ যোগ, সরানো বা পরিবর্তন করতে ব্যবহৃত হয়।int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epoll_wait()
:
epoll
instance-এর মধ্যে থাকা File Descriptor গুলোতে ইভেন্ট আছে কিনা তা চেক করে এবং এটি ইভেন্ট পাওয়া গেলে তাদের ফেরত দেয়।int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
epoll()
এর উদাহরণ#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#define PORT 8080
#define MAX_EVENTS 10
int main() {
int server_fd, client_fd, epoll_fd;
struct sockaddr_in server_addr;
struct epoll_event ev, events[MAX_EVENTS];
char buffer[1024];
// Server socket তৈরি করা
server_fd = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
listen(server_fd, 3);
// epoll instance তৈরি করা
epoll_fd = epoll_create(1);
ev.events = EPOLLIN;
ev.data.fd = server_fd;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev);
while (1) {
int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
for (int i = 0; i < num_events; i++) {
if (events[i].data.fd == server_fd) {
client_fd = accept(server_fd, NULL, NULL);
printf("New connection accepted\n");
ev.events = EPOLLIN;
ev.data.fd = client_fd;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev);
} else {
int client_fd = events[i].data.fd;
read(client_fd, buffer, sizeof(buffer));
printf("Received: %s\n", buffer);
close(client_fd);
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL);
}
}
}
close(server_fd);
close(epoll_fd);
return 0;
}
select()
, poll()
, এবং epoll()
বৈশিষ্ট্য | select() | poll() | epoll() |
---|---|---|---|
স্কেলেবিলিটি | সীমিত (1024 FD-এর বেশি পরিচালনা করতে পারে না) | উন্নত, কিন্তু select() এর মতো সমস্যা আছে | উচ্চ স্কেলেবিলিটি, অনেক বেশি FD পরিচালনা করতে পারে |
কর্মক্ষমতা | ধীর, কারণ এটি প্রতিটি কলের সময় সবকিছু স্ক্যান করে | তুলনামূলকভাবে ধীর | দ্রুত, কারণ এটি শুধুমাত্র Active FD-এর উপর কাজ করে |
ব্যবহারিকতা | ছোট অ্যাপ্লিকেশনের জন্য উপযুক্ত | মধ্যম স্কেল অ্যাপ্লিকেশনের জন্য | উচ্চ-পারফরম্যান্স এবং বড় অ্যাপ্লিকেশন এবং সার্ভারের জন্য |
পোর্টেবিলিটি | POSIX মান সম্মত, অনেক সিস্টেমে সমর্থিত | POSIX মান সম্মত, অনেক সিস্টেমে সমর্থিত | Linux নির্দিষ্ট |
common.read_more